package caracteristicas;

import java.util.LinkedList;

public class MomentosHu {

	private int classificacaoImagem;
	private double[][] imagem;
	private double xMassa;
	private double yMassa;
	
	public MomentosHu(LinkedList<Object> lista) {
		super();
		//classificacao da iamgem
		this.classificacaoImagem = (Integer) lista.get(0);
		//imagem
		this.imagem = clonarImagem((double[][])lista.get(1)) ;
		//coordenada x do centro de massa
		this.xMassa = momento(1, 0)/momento(0, 0);
		//coordenada y do centro de massa
		this.yMassa = momento(0, 1)/momento(0, 0);
		
	}
	
	private double[][] clonarImagem (double[][] imagemS){
		double retorno[][] = new double[imagemS.length][imagemS[0].length];
		for (int i = 0; i < retorno.length; i++) {
			retorno[i] = imagemS[i].clone();
		}
		return retorno;

	}

	
	private double momento (int p, int q){
		double momento = 0;
		for (int i = 0; i < this.imagem.length; i++) {
			for (int j = 0; j < this.imagem[0].length; j++) {
				momento += (Math.pow(i, p)) * (Math.pow(j, q)) * this.imagem[i][j]; 
				
			}
		}
		return momento;
	}
	
	private double momentoCentral (int p, int q){
		double momentoCentral = 0;
		for (int i = 0; i < this.imagem.length; i++) {
			for (int j = 0; j < this.imagem[0].length; j++) {
				momentoCentral += (Math.pow(i- xMassa, p)) * (Math.pow(j-yMassa, q)) * this.imagem[i][j]; 
				
			}
		}
		
		return momentoCentral;
	}
	
	private double momentoCentralNormalizado (int p, int q){
		double gama = ((p + q)/2.0) + 1;
		double momentoCentral = momento(p, q);
		double momentoCentral00 = momentoCentral(0,0);
		double momentoCentralNormalizado = momentoCentral/Math.pow(momentoCentral00, gama);
		return momentoCentralNormalizado;
	}
	
	public double[] momentosInvariantesHu (){
		double[] retorno = new double[7];
		//primeiro momento de hu 
		retorno[0] = momentoCentralNormalizado(2, 0) + momentoCentralNormalizado(0, 2);
		
		//segundo momento de hu
		retorno[1] = Math.pow((momentoCentralNormalizado(2, 0)-momentoCentralNormalizado(0, 2)), 2) +
			4 * Math.pow(momentoCentralNormalizado(1, 1), 2);
		
		//terceiro momento de hu
		retorno[2] = Math.pow((momentoCentralNormalizado(3, 0)-(3* momentoCentralNormalizado(1, 2))), 2) +
			Math.pow((3*momentoCentralNormalizado(2, 1) - momentoCentralNormalizado(0, 3)), 2);
		
		//quarto momento de hu
		retorno[3] = Math.pow((momentoCentralNormalizado(3, 0)+momentoCentralNormalizado(1, 2) ), 2) +
			Math.pow((momentoCentralNormalizado(2,1)+momentoCentralNormalizado(0,3)), 2);
		
		//quinto momento de hu
		retorno[4] = 
			(momentoCentralNormalizado(3, 0)-(3* momentoCentralNormalizado(1, 2)))   *
					
			(momentoCentralNormalizado(3, 0)+momentoCentralNormalizado(1,2)) *			
			
			(
					Math.pow((momentoCentralNormalizado(3, 0)+momentoCentralNormalizado(1, 2) ), 2) -
					3 *Math.pow((momentoCentralNormalizado(2,1)+momentoCentralNormalizado(0,3)), 2)
			)
			 +
			
			(3*momentoCentralNormalizado(2, 1) - momentoCentralNormalizado(0, 3)) *
					(momentoCentralNormalizado(2,1)+momentoCentralNormalizado(0,3)) *
				(
					3*Math.pow((momentoCentralNormalizado(3, 0)+momentoCentralNormalizado(1, 2) ), 2) -
					Math.pow((momentoCentralNormalizado(2,1)+momentoCentralNormalizado(0,3)), 2)
				);
		
		//sexto momento de hu
		retorno[5] = (momentoCentralNormalizado(2, 0) - momentoCentralNormalizado(0, 2)) * 	
		(
				((momentoCentralNormalizado(3, 0) + momentoCentralNormalizado(1, 2)) * 
						(momentoCentralNormalizado(3, 0) + momentoCentralNormalizado(1, 2))		
				)
				-
				((momentoCentralNormalizado(0, 3) + momentoCentralNormalizado(2, 1)) * 
						(momentoCentralNormalizado(0, 3) + momentoCentralNormalizado(2, 1))		
				)
				
		)+
		4*(momentoCentralNormalizado(1, 1))*
		(momentoCentralNormalizado(3, 0) + momentoCentralNormalizado(1, 2))*
		(momentoCentralNormalizado(0, 3) + momentoCentralNormalizado(2, 1));
		
		
		//sétimo momento de hu 
		retorno[6] = 
			(3*momentoCentralNormalizado(2, 1) - momentoCentralNormalizado(0, 3)) *
			(momentoCentralNormalizado(3, 0)+momentoCentralNormalizado(1, 2) ) *
			(
			  Math.pow((momentoCentralNormalizado(3, 0)+momentoCentralNormalizado(1, 2) ), 2)-
			  3*(Math.pow((momentoCentralNormalizado(2,1)+momentoCentralNormalizado(0,3)), 2))
			) -
			
			momentoCentralNormalizado(3, 0)-(3* momentoCentralNormalizado(1, 2))*
			momentoCentralNormalizado(2,1)+momentoCentralNormalizado(0,3)*
			
			(
			  3*Math.pow((momentoCentralNormalizado(3, 0)+momentoCentralNormalizado(1, 2) ), 2)-
			  Math.pow((momentoCentralNormalizado(2,1)+momentoCentralNormalizado(0,3)), 2)
			
			);

		return retorno;
	}
	
	
	
}
